﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using FieldDevice.ModBus;


namespace FieldDevice.Devices
{
    class DeviceACR120EL : Device
    {
        public DeviceACR120EL(byte address, string name)
            : base(DeviceCategory.PowerMeter, address, name)
        {
            Initialize();
        }

        public DeviceACR120EL(byte address)
            : base(DeviceCategory.PowerMeter, address)
        {
            Initialize();
        }
        void Initialize()
        {
            base.RequestRegister(Emulation.ACR120ELEmulator.ADDR_PT, 2);
            base.RequestRegister(Emulation.ACR120ELEmulator.ADDR_DIO, 37);
        }
        byte[] RegistersValue = new byte[522];

        int PT = 1;
        int CT = 1;
        ushort DPT = 1;
        ushort DCT = 1;
        ushort DPQ = 1;                         //功率小数点标志位
        ushort PQ = 0;                          //功率符号位
        float EPI = 0.00f;
        float EPE = 0.00f;
        float EQL = 0.00f;
        float EQC = 0.00f;


        public override void DebugReads()
        {
            if (DeviceManager.GlobalDeviceManager.ModBusIO.IsEmulation)
                this.UpdateReads();
            else
                base.DebugReads();
        }
        void FieldReads()
        {
            ReadRegValue(Emulation.ACR120ELEmulator.ADDR_DIO, 25);
        }

        void UpdateReads()
        {
            ReadRegValue(Emulation.ACR120ELEmulator.ADDR_DIO, 25);
            base.FireReadChangeEvent("ALL", 0.0f);
        }

        public void ReadRegValue(ushort DataAddr, ushort DataNumber)
        {
            RegistersValue = base.ReadRegister(DataAddr, DataNumber);
            FieldLib.ModBusPacket packet = new FieldLib.ModBusPacket(this.ModbusAddress, this.ModBusReadCommand,
                DataAddr, DataNumber);
            TranslateRegister(packet, RegistersValue);
        }

        #region



        /// <summary>
        /// 命令：07 03 0025 0001 95A7 响应： 07 20 0838 5BFC
        /// 命令：07 03 0025 0003 1466 响应： 07 2010 4808 38E8 C6E8
        /// </summary>
        /// <param name="value"></param>
        /// <param name="begin"></param>
        /// <param name="registeraddress"></param>
        /// <returns></returns>
        protected override float Translate(byte[] value, int begin, ushort registeraddress)
        {
            ushort tmpValue = value[begin];
            tmpValue <<= 8;
            tmpValue += value[begin + 1];

            switch (registeraddress)
            {
                case Emulation.ACR120ELEmulator.ADDR_PT:
                    PT = tmpValue;
                    break;
                case Emulation.ACR120ELEmulator.ADDR_CT:
                    CT = tmpValue;
                   RecordRead("Ratio",CT*PT);
                    break;
                case Emulation.ACR120ELEmulator.ADDR_DIO:
                    if ((tmpValue & 0x100) != 0)
                        this.RecordBooleanRead(OnOffValueName, true);
                    else
                        RecordBooleanRead(OnOffValueName, false);

                    //if ((tmpValue & 0x200) != 0)
                    //    RecordRead("DI2", 1);
                    //else
                    //    RecordRead("DI2", 0);

                    //if ((tmpValue & 0x400) != 0)
                    //    RecordRead("DI3", 1);
                    //else
                    //    RecordRead("DI3", 0);

                    //if ((tmpValue & 0x800) != 0)
                    //    RecordRead("DI3", 1);
                    //else
                    //    RecordRead("DI3", 0);

                    //if ((tmpValue & 0x1000) != 0)
                    //    RecordRead("DI4", 1);
                    //else
                    //    RecordRead("DI4", 0);

                    //if ((tmpValue & 0x2000) != 0)
                    //    RecordRead("DO1", 1);
                    //else
                    //    RecordRead("DO1", 0);

                    //if ((tmpValue & 0x4000) != 0)
                    //    RecordRead("DO2", 1);
                    //else
                    //    RecordRead("DO2", 0);
                    break;
                case Emulation.ACR120ELEmulator.ADDR_Flag_UI:
                    DPT = (ushort)(tmpValue >> 8);
                    DCT = (ushort)(tmpValue & 0x00ff);
                    break;
                case Emulation.ACR120ELEmulator.ADDR_Flag_P:
                    DPQ = (ushort)(tmpValue >> 8);
                    PQ = (ushort)(tmpValue & 0x00ff);
                    break;
                case Emulation.ACR120ELEmulator.ADDR_Va:
                    RecordRead("VA", tmpValue * (float)Math.Pow(10, (DPT - 4)));
                    break;

                case Emulation.ACR120ELEmulator.ADDR_Vb:
                    RecordRead("VB", tmpValue * (float)Math.Pow(10, (DPT - 4)));
                    break;

                case Emulation.ACR120ELEmulator.ADDR_Vc:
                    RecordRead("VC", tmpValue * (float)Math.Pow(10, (DPT - 4)));
                    break;

                case Emulation.ACR120ELEmulator.ADDR_Vab:
                    RecordRead("Vab", tmpValue * (float)Math.Pow(10, (DPT - 4)));
                    break;
                case Emulation.ACR120ELEmulator.ADDR_Vbc:
                    RecordRead("Vbc", tmpValue * (float)Math.Pow(10, (DPT - 4)));
                    break;

                case Emulation.ACR120ELEmulator.ADDR_Vca:
                    RecordRead("Vca", tmpValue * (float)Math.Pow(10, (DPT - 4)));
                    break;

                case Emulation.ACR120ELEmulator.ADDR_Ia:
                    RecordRead("IA", tmpValue * (float)Math.Pow(10, (DCT - 4)));
                    break;

                case Emulation.ACR120ELEmulator.ADDR_Ib:
                    RecordRead("IB", tmpValue * (float)Math.Pow(10, (DCT - 4)));
                    break;

                case Emulation.ACR120ELEmulator.ADDR_Ic:
                    RecordRead("IC", tmpValue * (float)Math.Pow(10, (DCT - 4)));
                    break;
                case Emulation.ACR120ELEmulator.ADDR_F:
                    RecordRead("FR", tmpValue / 100.0f);
                    break;

                case Emulation.ACR120ELEmulator.ADDR_PF:
                    RecordRead("PF", tmpValue / 1000.0f);
                    break;

                case Emulation.ACR120ELEmulator.ADDR_P:
                    if ((PQ & 0x08) != 0)
                        tmpValue = (ushort)(-1 * tmpValue);
                    RecordRead("P", tmpValue * (float)Math.Pow(10, (DPQ - 4)));
                    break;

                case Emulation.ACR120ELEmulator.ADDR_Q:
                    if ((PQ & 0x80) != 0)
                       tmpValue = (ushort)(-1 * tmpValue);
                    RecordRead("Q", tmpValue * (float)Math.Pow(10, (DPQ - 4)));
                    break;

                case Emulation.ACR120ELEmulator.ADDR_S:
                    RecordRead("S", tmpValue * (float)Math.Pow(10, (DPQ - 4)));
                    break;
                //case Emulation.ACR120ELEmulator.ADDR_EPE_Hi:
                //    EPE = tmpValue;
                //    break;
                //case Emulation.ACR120ELEmulator.ADDR_EPE_Low:
                //    EPE = EPE * 65536 + tmpValue;
                //    RecordRead("EPE", EPE);
                //    break;



                ///////////!!!Liu20120902////////////////////////////////////////
                // 参见ACR网络电力仪表说明书.pdf page 9
                //ACR仪表显示电能值时，LED（数码管）型指示的电能数据为一次侧电能，此值
                //无须再乘以电流、电压变比。LCD（液晶）型指示的电能数据为二次侧电能值，
                //该值乘以电流、电压变比才是一次侧电能值。
                case Emulation.ACR120ELEmulator.ADDR_EPI_Hi:
                    EPI = FieldLib.Utility.BytesToUInt_SmallEndian(value, begin);
               //     EPI = tmpValue;
               //     break;
               // case Emulation.ACR120ELEmulator.ADDR_EPI_Low:
               //     EPI = EPI * 65536 + tmpValue;
               // //float p = EPI * (float)Math.Pow(10, (DPQ - 4));
               ////EPI/=(this.Config.PowerRatio*1000.0f);  //进行电度倍率调整
               //     EPI=EPI/1000.0f*PT*CT;  //进行电度倍率调整
               //     RecordRead("EPI", EPI);
               //     break;

                 /////////////!!!!Liu20120902//////////////////////////
                  // 参见ACR网络电力仪表说明书.pdf   page 18
                 //分别读地址003FH～0040H(吸收有功电能)、0041H～0042H（释放有功电能）、
                 //0043H～0044H（感性无功电能）、0045H～0046H（容性无功电能）二次侧电能、
                 //再读PT、CT，按照下面公式计算：电能通讯读出值Val_t＝第一个word×65536+
                 //第二个word电能量一次侧值Val_s＝Val_t/1000×PT×CT，有功电能单位：千瓦时
                 //（kWh），无功电能单位：千乏时（kvarh）。其中PT从地址0003H里读出，CT从地址0004H里读出。
                    EPI=(EPI/1000.0f)*PT*CT;  //进行电度倍率调整
                    RecordRead("EPI", EPI);
                    break;
                   
                case Emulation.ACR120ELEmulator.ADDR_EQL_Hi:
                    EQL = tmpValue;
                    break;
                case Emulation.ACR120ELEmulator.ADDR_EQL_Low:
                    EQL = EQL * 65536 + tmpValue;
                    //float q = EQL * (float)Math.Pow(10, (DPQ - 4));
                    //EQL /= (this.Config.PowerRatio * 1000.0f);
                    EQL =(EQL / 1000.0f) * PT * CT ;
                    RecordRead("EQL", EQL);
                    break;
                //case Emulation.ACR120ELEmulator.ADDR_EQC_Hi:
                //    EQC = tmpValue;
                //    break;
                //case Emulation.ACR120ELEmulator.ADDR_EQC_Low:
                //    EQC = EQC * 65536 + tmpValue;
                //    RecordRead("EQC", EQC);
                //    break;
                default:
                    break;


            }
            return 0.0f;
        }
        # endregion

        public class ACR120ELConfig : DeviceConfigBase
        {
            public ACR120ELConfig()
            {
                this.PowerRatio = 1.0f;
            }

            [Category("电表参数"),Description("ACR120表面板读数与Modbus存在倍率关系。此参数设置此倍率关系")]
            public float PowerRatio { get; set; }
        }

        private ACR120ELConfig ACR120Config=new ACR120ELConfig();

        protected override DeviceConfigBase GetDeviceConfig()
        {
            return ACR120Config;
        }

        protected override void SetDeviceConfig(Device.DeviceConfigBase config)
        {
            base.SetDeviceConfig(config);
            if (config is ACR120ELConfig)
            {
                this.ACR120Config = (ACR120ELConfig)config;
            }
        }
    }
}

